﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArtificialIntelligence.MovementComponent.AStar;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Factories;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XNA_2DFramwork;
using Microsoft.Xna.Framework;

namespace ArtificialIntelligence.CombatComponent
{
    public class Agent :VisualObject
    {
        public List<Schedule> LAgentSchedules;
        public List<PathNode> LPath;
        public Schedule RunningSchedule;
        
        public AgentState AgentState;
        
        public EnemySensor EnemySensor;
        
        private Rectangle r;
        private Shoot S;
        public Agent(Game Game, int width, int height, Vector2 position, string filename, GraphicsDevice gd, PhysicsSimulator physicsSimulator)
            : base(Game)
        {
            
            AgentState = new AgentState();
            AgentState = AgentState.Ideal;

            LAgentSchedules = new List<Schedule>();
            LPath = new List<PathNode>();

            PhysicsSimulator = physicsSimulator;
            Position = position;
            EnemySensor = new EnemySensor(Game, PhysicsSimulator, Position, gd, 200);
            //---------------------------------------------------------------------------------------
            Texture = Game.Content.Load<Texture2D>(filename);
            Width = width;
            Height = height;
            Origin = new Vector2(Width / 2f, Height / 2f);
            SpriteBatch = new SpriteBatch(gd);
            Body = BodyFactory.Instance.CreateRectangleBody(PhysicsSimulator, Width, Height, 1);
            Body.Position = Position;
            Geom = GeomFactory.Instance.CreateRectangleGeom(PhysicsSimulator, Body, Width, Height);
            Geom.FrictionCoefficient = 1;
            //Geom.CollisionResponseEnabled = false;
            r = new Rectangle(0, 0, Width, Height);
            S = new Shoot(Game, physicsSimulator, gd, Body.Position);
        }

        public int Life;

        public int Power;

       
        public override void Draw()
        {

            S.Draw();
            SpriteBatch.Begin();
            SpriteBatch.Draw(Texture, Body.Position, r, Color.White, Body.Rotation, Origin,1f,
                SpriteEffects.None,0f);
            SpriteBatch.End();
            EnemySensor.Draw();
        }

        public override void Update()
        {

            RunSchedules();
            S.Update();
            if (Keyboard.GetState().IsKeyDown(Keys.Enter))
                S.Walk(new Vector2(0,0));           
            EnemySensor.Body.Position = Body.Position;
            if (EnemySensor.IsSeriouslyDamaged(Life))
                EnemySensor.sensedItem.SensorState = SensorState.SeriousDamage;
            if (EnemySensor.IsSeeingEnemy())
                EnemySensor.sensedItem.SensorState = SensorState.SeeingEnemy;
            if (AgentState == AgentState.Ideal)
            {
                EnemySensor.sensedItem.SensorState = SensorState.Safe;
            }
        }
        public void RunSchedules ()
        {
            #region
            //foreach (Schedule lAgentSchedule in LAgentSchedules)
            //{
            //    lAgentSchedule.Run(lAgentScheduleType);
            //}
            #endregion
            SetRunningSchedule( GetHighestPriority(LAgentSchedules));
        }

        public void SetRunningSchedule(Schedule schedule)
        {
            RunningSchedule = schedule;
            ScheduleState scheduleState = RunningSchedule.Run(RunningSchedule.scheduleType, this);
            if (scheduleState == ScheduleState.Excuted)
                LAgentSchedules.Remove(schedule);
            else
            {
                if (scheduleState == ScheduleState.ObjectNotFound)
                {
                    InferenceMachine._missions.Remove(schedule);
                }
                if (scheduleState == ScheduleState.Failed)
                {
                    //leave it in the missions to be excuted by another agent
                }
            }
        }


        public Schedule GetHighestPriority(List<Schedule>List)
        {
            Schedule highestSchedule = new Schedule(ScheduleType.Ideal);
            foreach (Schedule schedule in List)
            {
                if (schedule.Priority > highestSchedule.Priority)
                {
                    highestSchedule = schedule;
                }
            }
            return highestSchedule;
        }

        public Vector2 FindObject(List<VisualObject> list, ObjectType type, Vector2 agentPlace)
        {
            List<VisualObject> lSameType = new List<VisualObject>();
            foreach (VisualObject visualObject in list)
            {
                if (visualObject.Type == type)
                {
                    lSameType.Add(visualObject);
                }
            }
            if (lSameType.Count ==0)
                return new Vector2(0,0);

            return (GetNearestObject(lSameType, agentPlace).Position);
        }

        //public void FindPathTo(List<Node<Vector2>> domain, Node<Vector2> startPoint, Node<Vector2> goalPoint)
        //{
        //    Path.FindPathByAStarSearch(domain, startPoint, goalPoint);
        //}

        public void AttackObject()
        {
        }

        public void HideBehindObject()
        {

        }

        public void StopMoving()
        {
        }

        public void Move(List<PathNode> path)
        {
            for (int i = 0; i < path.Count; i++)
            {
                MoveToPoint(path[i].Point,LPath);
            }

        }

        public VisualObject GetNearestObject( List<VisualObject> list, Vector2 agentPosition)
        {
            //Vector2 nearestposition = new Vector2(0,0);
            int index = 0;
            float differenceX = 0f;
            float differenceY = 0f;
            for (int i =0; i < list.Count; i ++)
            {
                if ( ( list[i].Position.X - agentPosition.X) < differenceX &&  (list[i].Position.Y - agentPosition.Y) < differenceY)
                {
                    differenceX = list[i].Position.X - agentPosition.X;
                    differenceY = list[i].Position.Y - agentPosition.Y;
                    //nearestposition = list[i].Position;
                    index = i;
                }
            }
            return list[index];
        }

    }
}
